package com.ihome.android.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import com.ihome.android.common.ComParams;
import com.ihome.android.util.log.LogUtil;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;

public class BgInstallApk {
	private static final String	TAG			= BgInstallApk.class.getSimpleName();

	public static Object[] installAppInBackGround(String apkFilePath, String args) {
		String params = "pm install " + (args == null ? "" : args + " ") + apkFilePath;
		return excuteShellComm(params);
	}

	public static Object[] enableAppInBackGround(String pkgName, String args) {
		String params = "pm enable " + (args == null ? "" : args + " ") + pkgName;
		return excuteShellComm(params);
	}

	public static Object[] uninstallAppInBackGround(String packageName) {
		String args = "pm uninstall " + packageName;
		return excuteShellComm(args);
	}

	public static boolean startApp(Context ctx, String pName) {
		PackageManager pm = ctx.getPackageManager();
		Intent intent = pm.getLaunchIntentForPackage(pName);
		if (intent != null) {
			if (!(ctx instanceof Activity)) {
				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			}
			ctx.startActivity(intent);
			LogUtil.d(TAG, "Upgrade-->restart App" + intent);
		}
		return false;
	}

	/**
	 * Silent install APK application through the 'pm' command， Need to apply
	 * for a 'android. Permission. INSTALL_PACKAGES' permission
	 * 
	 * @param params
	 *            apk file path
	 * @return  Object[]
	 * Object[0]:true-success,false-failed
	 * Object[1]:"" if success or failure content
	 */
	public static Object[] excuteShellComm(String params) {
		String rsltStr = "";
		Object[] result = new Object[2];
		
		result[0] = Boolean.valueOf(false);
		result[1] = "";

		if (params == null){
			result[0] = Boolean.valueOf(false);
			result[1] = ComParams.ERROR_INVALID_PARAMETER;
			return result;
		}
			
		Process process = null;
		InputStream errIs = null;
		InputStream inIs = null;

		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			int read = -1;
			process = Runtime.getRuntime().exec(params);
			inIs = process.getInputStream();
			while ((read = inIs.read()) != -1) {
				baos.write(read);
			}
			baos.flush();
			byte[] data = baos.toByteArray();
			rsltStr = new String(data);

			LogUtil.v(TAG, "executeShell rsltStr = " + rsltStr);
			if (rsltStr.toLowerCase().contains("success")) {
				result[0] = Boolean.valueOf(true);
				result[1] = "";
				LogUtil.i(TAG, "shell-->success:" + params);
			}
			else {
				baos.reset();
				errIs = process.getErrorStream();
				while ((read = errIs.read()) != -1) {
					baos.write(read);
				}
				baos.flush();
				byte[] data1 = baos.toByteArray();
				
				result[0] = Boolean.valueOf(false);
				result[1] = new String(data1);
				
				LogUtil.e(TAG, "shell-->fail:" + params + "\n MSG:" + result[1]);
			}
		} catch (Exception e) {
			result[0] = Boolean.valueOf(false);
			result[1] = e.getCause().getMessage();
			e.printStackTrace();
		} finally {
			try {
				if (errIs != null) {
					errIs.close();
				}
				if (inIs != null) {
					inIs.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (process != null) {
				process.destroy();
			}
		}
		return result;
	}

	public static boolean doUninstallationSliently(String pkgName) {
		boolean flag = false;
		Process process = null;
		try {
			process = new ProcessBuilder().command("/system/bin/pm", "uninstall", pkgName).redirectErrorStream(true).start();
			LogUtil.v(TAG, "pkgName = " + pkgName);
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			InputStream in = process.getInputStream();
			byte[] b = new byte[20];
			while (in.read(b, 0, 20) != -1) {
				String tmp = new String(b);
				if (tmp.indexOf("Success") != -1) {
					flag = true;
					break;
				}
				LogUtil.d("doUninstallationSliently tem  = ", tmp);
			}
			if (flag)
				LogUtil.i(TAG, "doUninstallationSliently success ");
			else
				LogUtil.e(TAG, "doUninstallationSliently failed ");
			process.destroy();
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			process.destroy();
		}
		return flag;
	}

	public static void enableApp(Context ctx, String pName, boolean enable) {
		try {
			PackageManager pm = ctx.getPackageManager();
			if (enable)
				pm.setApplicationEnabledSetting(pName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
			else
				pm.setApplicationEnabledSetting(pName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * get packageinfo by pName has installed app
	 * 
	 * @param ctx
	 *            Context
	 * @param pName
	 * @return PackageInfo if not find return null
	 */
	public static PackageInfo getPackageInfoByAppName(Context ctx, String pName) {
		PackageInfo pInfo = null;
		if (pName != null) {
			PackageManager pm = ctx.getPackageManager();
			try {
				pInfo = pm.getPackageInfo(pName, PackageManager.GET_SIGNATURES);
			} catch (NameNotFoundException e) {
				e.printStackTrace();
				LogUtil.e(TAG, e.getMessage());
			}
		}
		return pInfo;
	}

	public static String getProcessNameByPID(Context context, int pid) {
		String appName = null;
		ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

		for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
			if (processInfo.pid == pid) {
				appName = processInfo.processName;
				break;
			}
		}
		return appName;
	}

	public static PackageInfo getPackageInfoByProcessName(Context context, String processName) {
		PackageManager pm = context.getPackageManager();
		List<PackageInfo> packages = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);
		for (int i = 0; i < packages.size(); i++) {
			PackageInfo packageInfo = packages.get(i);
			if (packageInfo.applicationInfo.processName.equals(processName)) {
				return packageInfo;
			}
		}
		return null;
	}

	public static void doInstallation(Context context, String apkpath) {
		try {
			Intent intent = new Intent(Intent.ACTION_VIEW);
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			intent.setComponent(new ComponentName("com.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity"));
			intent.setDataAndType(Uri.fromFile(new File(apkpath)), "application/vnd.android.package-archive");
			context.startActivity(intent);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void doUnInstall(Context context, String apkPkgName) {
		try {
			Intent intent = new Intent();
			intent.setAction(Intent.ACTION_DELETE);
			intent.addCategory(Intent.CATEGORY_DEFAULT);
			intent.setData(Uri.parse("package:" + apkPkgName));
			context.startActivity(intent);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
